package com.niiwoo.civet.trade.service.local.auth;

import com.dangdang.ddframe.rdb.sharding.api.HintManager;
import com.dangdang.ddframe.rdb.sharding.hint.HintManagerHolder;
import com.niiwoo.civet.trade.dao.entity.Project;
import com.niiwoo.civet.trade.dao.entity.ProjectFlowExecute;
import com.niiwoo.civet.trade.dao.entity.ProjectFlowExecuteRuntime;
import com.niiwoo.civet.trade.dao.mapper.ProjectFlowExecuteMapperExt;
import com.niiwoo.civet.trade.dao.mapper.ProjectFlowExecuteRuntimeMapperExt;
import com.niiwoo.civet.trade.dao.mapper.ProjectMapperExt;
import com.niiwoo.civet.trade.dto.request.ProjectFlowRequestDTO;
import com.niiwoo.civet.trade.enums.*;
import com.niiwoo.civet.trade.service.local.flowexecute.ProjectFlowExecuteService;
import com.niiwoo.civet.trade.service.local.loan.LoanReturnService;
import com.niiwoo.civet.trade.service.project.ProjectDubboService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.aop.framework.AopContext;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Transactional;

/**
 * @author wping
 * @Description: 授权服务类
 * @date 2018/4/20 20:47
 */
@Slf4j
@Service
public class AuthService {

    // 执行次数阈值
    private static final int EXECUTE_TIMES_THRESHOLD = 3;

    @Autowired
    private ProjectFlowExecuteMapperExt projectFlowExecuteMapperExt;

    @Autowired
    private ProjectFlowExecuteRuntimeMapperExt projectFlowExecuteRuntimeMapperExt;

    @Autowired
    private ProjectFlowExecuteService projectFlowExecuteService;

    @Autowired
    private LoanReturnService loanReturnService;

    @Autowired
    private ProjectMapperExt projectMapperExt;

    @Autowired
    private SmallLoanAuthCheckService smallLoanAuthCheckService;

    @Autowired
    private SocialSecurityLoanAuthCheckService socialSecurityLoanAuthCheckService;

    @Autowired
    private CreditCardLoanAuthCheckService creditCardLoanAuthCheckService;
    
    @Autowired
    private ConsumeLoanAuthCheckService consumeLoanAuthCheckService;

    @Autowired
    private ProjectDubboService projectDubboService;

    public void executeAuthStatusCheck(Long flowExecuteId) {

        String methodName = "授权数据检查, flowExecuteId:" + flowExecuteId;

        AuthService authService = (AuthService)AopContext.currentProxy();

        if (!HintManagerHolder.isMasterRouteOnly()) {
            HintManagerHolder.clear();
            HintManager hintManager = HintManager.getInstance();
            hintManager.setMasterRouteOnly();
        }
        ProjectFlowExecute projectFlowExecute = projectFlowExecuteMapperExt.selectByPrimaryKey(flowExecuteId);
        if (projectFlowExecute == null || projectFlowExecute.getProjectType() == null) {
            log.error(methodName + "-失败，ProjectFlowExecute记录不存在或者projectType为空");
            return;
        }

        if (projectFlowExecute.getStatus() != null && ProjectFlowExecuteStatusEnum.EXECUTING.getStatus() != projectFlowExecute.getStatus().byteValue()) {
            log.info(methodName + "-流程已经结束，退出不更新");
            return;
        }

        if (!HintManagerHolder.isMasterRouteOnly()) {
            HintManagerHolder.clear();
            HintManager hintManager = HintManager.getInstance();
            hintManager.setMasterRouteOnly();
        }
        ProjectFlowExecuteRuntime projectFlowExecuteRuntime = projectFlowExecuteRuntimeMapperExt.selectByPrimaryKey(flowExecuteId);
        if (projectFlowExecuteRuntime == null) {
            log.error(methodName + "-失败，ProjectFlowExecuteRuntime记录不存在");
            authService.failEndProjectFlowExecuteAndReturnProject(flowExecuteId, projectFlowExecute.getProjectId(), ReturnProjectReasonTypeEnum.OTHER_EXCEPTION, "ProjectFlowExecuteRuntime记录不存在");
            return;
        }

        if (LoanNodeTypeEnum.AUTH_STATUS_CHECK.getId() != projectFlowExecuteRuntime.getNodeId().intValue()) {
            log.error(methodName + "-失败，当前节点并非授权状态检测，ProjectFlowExecuteRuntime.nodeId:{}", projectFlowExecuteRuntime.getNodeId());
            return;
        }

        String userId = projectFlowExecute.getBorrowUserId();
        Long projectId = projectFlowExecute.getProjectId();
        methodName += ", userId:" + userId + ", projectId:" + projectId;
        // 判断标的状态
        if (!HintManagerHolder.isMasterRouteOnly()) {
            HintManagerHolder.clear();
            HintManager hintManager = HintManager.getInstance();
            hintManager.setMasterRouteOnly();
        }
        Project project = projectMapperExt.selectByPrimaryKey(projectId);
        if (project == null) {
            log.error(methodName + "-标的不存在");
            authService.failEndProjectFlowExecute(flowExecuteId, "标的不存在");
            return;
        }

        if (!(project.getStatus().equals(ProjectStatusEnum.CHECKING.getStatus())
                && project.getSubStatus().equals(ProjectSubStatusEnum.CHECKING_INIT.getSubStatus()))) {
            log.error(methodName + "-标的状态不在审核中, 当前标的状态:{}", project.getStatus());
            authService.failEndProjectFlowExecute(flowExecuteId, "标的状态不在审核中, 当前标的状态:" + project.getStatus());
            return;
        }

        int currentExecuteTimes = projectFlowExecuteRuntime.getRetryTimes() == null ? 1 : projectFlowExecuteRuntime.getRetryTimes() + 1;

        if (ProjectTypeEnum.SMALL_LOAN.getValue() == projectFlowExecute.getProjectType().byteValue()) {
            smallLoanAuthCheckService.authCheck(flowExecuteId, userId, projectId, currentExecuteTimes);
        } else if (ProjectTypeEnum.SOCIAL_SECURITY_LOAN.getValue() == projectFlowExecute.getProjectType().byteValue()) {
            socialSecurityLoanAuthCheckService.authCheck(flowExecuteId, userId, projectId, currentExecuteTimes);
        } else if (ProjectTypeEnum.CREDIT_CARD_LOAN.getValue() == projectFlowExecute.getProjectType().byteValue()) {
            creditCardLoanAuthCheckService.authCheck(flowExecuteId, userId, projectId, currentExecuteTimes);
        } else if (ProjectTypeEnum.CONSUME_LOAN.getValue().equals(projectFlowExecute.getProjectType())) {
        	consumeLoanAuthCheckService.authCheck(flowExecuteId, userId, projectId, currentExecuteTimes);
        }
    }

    /**
     * 授权状态检测结束流程并且退回标的
     *
     * @param flowExecuteId
     * @param projectId
     * @param reasonTypeEnum
     * @param errMsg
     * @return
     */
    @Transactional(isolation = Isolation.READ_COMMITTED, rollbackFor = Exception.class)
    public boolean failEndProjectFlowExecuteAndReturnProject(Long flowExecuteId, Long projectId, ReturnProjectReasonTypeEnum reasonTypeEnum, String errMsg) {
        boolean result = failEndProjectFlowExecute(flowExecuteId, errMsg);

        if (!HintManagerHolder.isMasterRouteOnly()) {
            HintManagerHolder.clear();
            HintManager hintManager = HintManager.getInstance();
            hintManager.setMasterRouteOnly();
        }
        Project project = projectMapperExt.selectByPrimaryKey(projectId);
        if (project != null && project.getFromSource() != null && ProjectFromSourceEnum.HUIJIE.getType() == project.getFromSource().byteValue()) {
            ProjectFlowRequestDTO projectFlowRequestDTO = new ProjectFlowRequestDTO();
            projectFlowRequestDTO.setProjectId(projectId);
            projectFlowRequestDTO.setSubStatus(ProjectSubStatusEnum.MISCARRY_CANCER_BORROWER);
            projectDubboService.flow(projectFlowRequestDTO);
            //TODO GWP 流标通知汇介asset端
        } else {
            returnProject(projectId, reasonTypeEnum);
        }

        return result;
    }

    public boolean failEndProjectFlowExecute(Long flowExecuteId, String errMsg) {
        return projectFlowExecuteService.failEndProjectFlowExecute(flowExecuteId, LoanNodeTypeEnum.AUTH_STATUS_CHECK, errMsg);
    }

    public void returnProject(Long projectId, ReturnProjectReasonTypeEnum reasonTypeEnum) {
        loanReturnService.returnProject(projectId, ProjectSubStatusEnum.CHECKING_BACK_PHONEOPERATOR_TIMEOUT, reasonTypeEnum);
    }

}
